package com.trt.user.controller;

import com.trt.api.BaseController;
import com.trt.api.controller.user.PassportControllerApi;
import com.trt.enums.ResponseStatusEnum;
import com.trt.enums.UserStatus;
import com.trt.pojo.AppUser;
import com.trt.pojo.dto.RegistLoginBO;
import com.trt.user.service.IUserService;
import com.trt.utils.ApiResult;
import com.trt.utils.IPUtil;
import com.trt.utils.JsonUtils;
import com.trt.utils.SMSUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Map;
import java.util.UUID;


/**
 * @author tanrentao
 * @date 2021-12-01
 * @desc 登录注册
 */
@RestController
public class PassportController extends BaseController implements PassportControllerApi {

    final static Logger logger = LoggerFactory.getLogger(PassportController.class);

    @Autowired
    private SMSUtils smsUtils;

    @Autowired
    private IUserService userService;

    @Override
    public ApiResult getSMSCode(String mobile, HttpServletRequest request) {

        // 获取用户ip
        String userIp = IPUtil.getRequestIp(request);

        // 根据用户的ip进行限制，限制用户在60秒内只能获得一次验证码
        redisUtils.setnx60s(MOBILE_SMSCODE + ":" + userIp, userIp);

        // 生成随机验证码并且发送短信
        String random = (int)((Math.random() * 9 + 1) * 100000) + "";
        smsUtils.sendSMS(mobile, random);

        // 把验证码存入redis，用于后续进行验证
        redisUtils.set(MOBILE_SMSCODE + ":" + mobile, random, 30 * 60);

        return ApiResult.success();
    }

    @Override
    public ApiResult login(@Valid RegistLoginBO registLoginBO, BindingResult result, HttpServletResponse response) {
        // 1.判断BindingResult中是否保存了错误的验证信息，如果有，则需要返回
        if (result.hasErrors()) {
            Map<String, String> map = getErrors(result);
            return ApiResult.errorMap(map);
        }

        String mobile = registLoginBO.getMobile();
        String smsCode = registLoginBO.getSmsCode();

        // 2.校验验证码是否匹配
        String redisSMSCode = redisUtils.get(MOBILE_SMSCODE + ":" + mobile);
        if (StringUtils.isBlank(redisSMSCode) || !redisSMSCode.equalsIgnoreCase(smsCode)) {
            return ApiResult.errorCustom(ResponseStatusEnum.SMS_CODE_ERROR);
        }

        // 3.查询数据库，判断该用户注册
        AppUser appUser = userService.selectAppUserIsExistByMobile(mobile);
        if (appUser != null && appUser.getActiveStatus().equals(UserStatus.FROZEN.type)) {
            // 如果用户不为空，并且状态为冻结，则直接抛出异常，禁止登录
            return ApiResult.errorCustom(ResponseStatusEnum.USER_FROZEN);
        } else if (appUser == null) {
            // 如果用户没有注册过，则为null，需要注册信息入库
            appUser = userService.createUser(mobile);
        }

        // 4.保存用户分布式会话的相关操作
        Integer userActiveStatus = appUser.getActiveStatus();
        if (!userActiveStatus.equals(UserStatus.FROZEN.type)) {
            // 保存token到redis
            String token = UUID.randomUUID().toString();
            redisUtils.set(REDIS_USER_TOKEN + ":" + appUser.getId(), token);
            redisUtils.set(REDIS_USER_INFO + ":" + appUser.getId(), JsonUtils.objectToJson(appUser));

            // 保存用户id和token到cookie中
            setCookie(response, "token", token, COOKIE_MONTH);
            setCookie(response, "userId", appUser.getId(), COOKIE_MONTH);
        }

        // 5.用户登录或注册成功以后，需要删除redis中的短信验证码，验证码只能使用一次，用过后则作废
        redisUtils.del(MOBILE_SMSCODE + ":" + mobile);

        // 6. 返回用户状态
        return ApiResult.success(userActiveStatus);
    }

    @Override
    public ApiResult logout(String userId, HttpServletResponse response) {
        redisUtils.del(REDIS_USER_TOKEN + ":" + userId);
        setCookie(response, "token", "", COOKIE_DELETE);
        setCookie(response, "userId", "", COOKIE_DELETE);
        return ApiResult.success();
    }


}
